using System;
using System.Collections.Generic;
using System.IO;
using EditorExtension;
using UnityEditor;

using UnityEditorInternal;
using UnityEngine;
using UnityEngine.AssetStandardProcessors;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Gameplay.City;
using System.Reflection;

namespace Yoozoo.Gameplay.CityEditor
{
    /*
     * 导出规则说明:
     * ground节点(以ground_2节点为例):
     *      1.解锁地面节点(mesh_innercity_floor_01_a (2))、解锁地面动画(sfx_ui_jiedao_zhanling_1)、未解锁地面节点(mesh_innercity_floor_02_before)，这三个节点下要显示的物件必须拖成prefab，不可以是fbx；
     *      2.未解锁地面节点(mesh_innercity_floor_02_before)不会整个作为prefab导出，所以别在上面挂其他组件！其他两个节点可以；
     *      3.未解锁地面节点下请根据LOD0,LOD1,LOD2来分级场景中的物件，命名请规范；
     */
    
    [CustomEditor(typeof(CityFloorEditor))]
    public class CityFloorEditorEditor : UnityEditor.Editor
    {
        private CityFloorEditor _cityFloorEditor;
        // 导出数据的路径
        private string _exportDataFilePath;
        // 导出预设的路径
        private string _exportPrefabFilePath;
        // 导出依赖预设的路径
        private string _exportDependencePath;
        // 依赖资源文件
        private Dictionary<string, string> _dependenceFilesDict;
        
        private void OnEnable()
        {
            _cityFloorEditor = target as CityFloorEditor;
            // _cityFloorEditor.UnlockAreas(0);
        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            
            CreateWallPreviewButtons();

            base.OnInspectorGUI();
            
            if (GUILayout.Button("更新CityWallComponent数据", GUILayout.Height(30)))
            {
                GameObject rootPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath);
                
                CityFloorEditor cityFloorEditor = rootPrefab.GetComponent<CityFloorEditor>();
                CityWallComponent cityWallComponent = rootPrefab.GetComponentInChildren<CityWallComponent>();
                cityWallComponent.areaWallDataList = new List<AreaWallData>();
                for (int i = 0; i < cityFloorEditor.areas.Count; ++i)
                {
                    CityFloorEditor.CityFloorEditorArea cityFloorEditorArea = cityFloorEditor.areas[i];
                    UnityEngine.Debug.LogError(i);
                    AreaWallData areaWallData = new AreaWallData
                    {
                        areaId = cityFloorEditorArea.areaId,
                        showWalls = cityFloorEditorArea.showWalls,
                        lookAtPoint = cityFloorEditorArea.lookAtPoint,
                        zoomDistance = cityFloorEditorArea.zoomDistance,
                    };
                    if (cityFloorEditorArea.lockFloorNode)
                    {
                        areaWallData.lockGround = cityFloorEditorArea.lockFloorNode.gameObject;
                    }
                    if (cityFloorEditorArea.unlockFloorNode)
                    {
                        areaWallData.unlockGround = cityFloorEditorArea.unlockFloorNode.gameObject;
                    }
                    if (cityFloorEditorArea.unlockEffectNode)
                    {
                        areaWallData.unlockGroundEffect = cityFloorEditorArea.unlockEffectNode.gameObject;
                    }
                    if (cityFloorEditorArea.unlockFogAni)
                    {
                        areaWallData.unlockFogAni = cityFloorEditorArea.unlockFogAni.gameObject;
                    }

                    if (cityFloorEditorArea.unlockWater)
                    {
                        areaWallData.unlockWater = cityFloorEditorArea.unlockWater.gameObject;
                    }

                    if (cityFloorEditorArea.containerEffect)
                    {
                        areaWallData.containerEffect = cityFloorEditorArea.containerEffect.gameObject;
                    }
                    
                    cityWallComponent.areaWallDataList.Add(areaWallData);
                }

                PrefabUtility.SavePrefabAsset(rootPrefab);
                AssetDatabase.Refresh(); 
            }
            
            GUILayout.BeginHorizontal();
            if (GUILayout.Button("导出数据",GUILayout.Height(30)))
            {
                // 关闭资源检测
                AssetGraphPostprocessor.Postprocessor.Enabled = false;
                
                _exportDataFilePath = $"{_cityFloorEditor.exportPath}/{_cityFloorEditor.transform.root.name}_Runtime.asset";
                _exportPrefabFilePath = $"{_cityFloorEditor.exportPath}/{_cityFloorEditor.transform.root.name}_Runtime.prefab";
                _exportDependencePath = $"{_cityFloorEditor.exportPath}/Dependences";
                FileUtility.DeleteDirectory(_cityFloorEditor.exportPath, true);
                Directory.CreateDirectory(_cityFloorEditor.exportPath);
                Directory.CreateDirectory(_exportDependencePath);
                AssetDatabase.Refresh();
                if (_dependenceFilesDict == null)
                {
                    _dependenceFilesDict = new Dictionary<string, string>();
                }
                _dependenceFilesDict.Clear();

                ClearConsole();
                
                ExportCityFloor();
                ExportPrefab();
                CopyDependence();
                
                AssetDatabase.Refresh();
                
                // 开启资源检测
                AssetGraphPostprocessor.Postprocessor.Enabled = true;
            }
            GUILayout.EndHorizontal();
            
            // if (GUILayout.Button("导入CityWallComponent数据", GUILayout.Height(30)))
            // {
            //     GameObject rootPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath);
            //     GameObject exportGO = PrefabUtility.InstantiatePrefab(rootPrefab) as GameObject;
            //     PrefabUtility.UnpackPrefabInstance(exportGO, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction);
            //     
            //     CityFloorEditor cityFloorEditor = exportGO.GetComponent<CityFloorEditor>();
            //     CityWallComponent cityWallComponent = exportGO.GetComponentInChildren<CityWallComponent>();
            //     for (int i = 0; i < cityWallComponent.areaWallDataList.Count; ++i)
            //     {
            //         int index = cityWallComponent.areaWallDataList[i].areaId - 1;
            //         cityFloorEditor.areas[index].lookAtPoint = cityWallComponent.areaWallDataList[i].lookAtPoint;
            //         cityFloorEditor.areas[index].zoomDistance = cityWallComponent.areaWallDataList[i].zoomDistance;
            //         cityFloorEditor.areas[index].showWalls = cityWallComponent.areaWallDataList[i].showWalls;
            //     }
            //     
            //     PrefabUtility.SaveAsPrefabAsset(exportGO, "Assets/CityRootTest_1.prefab");
            //     AssetDatabase.Refresh(); 
            // }

            serializedObject.ApplyModifiedProperties();
        }

    #region 预览隔离墙

        void CreateWallPreviewButtons()
        {
            // GUILayout.BeginHorizontal();
            // CreateUnlockAreaButton(9);
            // CreateUnlockAreaButton(8);
            // CreateUnlockAreaButton(7);
            // GUILayout.EndHorizontal();
            
            GUILayout.BeginHorizontal();
            CreateUnlockAreaButton(1);
            CreateUnlockAreaButton(2);
            CreateUnlockAreaButton(3);
            GUILayout.EndHorizontal();
            
            GUILayout.BeginHorizontal();
            CreateUnlockAreaButton(4);
            CreateUnlockAreaButton(5);
            CreateUnlockAreaButton(6);
            GUILayout.EndHorizontal();
            
            GUILayout.BeginHorizontal();
            CreateUnlockAreaButton(7);
            CreateUnlockAreaButton(8);
            CreateUnlockAreaButton(9);
            GUILayout.EndHorizontal();
            
            GUILayout.BeginHorizontal();
            CreateUnlockAreaButton(10);
            CreateUnlockAreaButton(11);
            CreateUnlockAreaButton(12);
            GUILayout.EndHorizontal();
            
            GUILayout.BeginHorizontal();
            CreateUnlockAreaButton(13);
            CreateUnlockAreaButton(14);
            CreateUnlockAreaButton(15);
            GUILayout.EndHorizontal();
            
            GUILayout.BeginHorizontal();
            CreateUnlockAreaButton(16);
            CreateUnlockAreaButton(17);
            CreateUnlockAreaButton(18);
            GUILayout.EndHorizontal();
            
            GUILayout.BeginHorizontal();
            CreateUnlockAreaButton(19);
            GUILayout.EndHorizontal();
        }
        void CreateUnlockAreaButton(int areaId)
        {
            if (GUILayout.Button("区域" + areaId, GUILayout.Height(30)))
            {
                _cityFloorEditor.UnlockAreas(areaId);
            }
        }

    #endregion


        /// <summary>
        /// 导出预设
        /// </summary>
        /// <param name="prefabPath"></param>
        void ExportPrefab()
        {
            if (UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage()==null || string.IsNullOrEmpty(UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath))
            {
                Debug.LogError("请打开Prefab再点击导出");
                return;
            }
            
            GameObject rootPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(UnityEditor.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage().prefabAssetPath);
            GameObject exportGO = PrefabUtility.InstantiatePrefab(rootPrefab) as GameObject;
                        
            // 注意！！要unpack所有父级和本级的prefab，才可以用代码修改节点
            PrefabUtility.UnpackPrefabInstance(exportGO, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction);
            CityFloorEditor cityFloorEditor = exportGO.GetComponent<CityFloorEditor>();
            if (IsPrefabInstance(cityFloorEditor.rootFloorNode.gameObject))
            {
                PrefabUtility.UnpackPrefabInstance(cityFloorEditor.rootFloorNode.gameObject, PrefabUnpackMode.OutermostRoot, InteractionMode.AutomatedAction);
            }
            
            for (int i = 0; i < cityFloorEditor.areas.Count; ++i)
            {
                CityFloorEditor.CityFloorEditorArea areaEditorData = cityFloorEditor.areas[i];
                // Wall节点
                if (areaEditorData.wallNode)
                {
                    GameObject.DestroyImmediate(areaEditorData.wallNode.gameObject);
                }
                // 解锁Floor节点
                if (areaEditorData.unlockFloorNode)
                {
                    GameObject.DestroyImmediate(areaEditorData.unlockFloorNode.gameObject);
                }
                // 解锁Floor节点
                if (areaEditorData.unlockEffectNode)
                {
                    GameObject.DestroyImmediate(areaEditorData.unlockEffectNode.gameObject);
                }
                // 未解锁Floor节点
                if (areaEditorData.lockFloorNode)
                {
                    int childCount = areaEditorData.lockFloorNode.childCount;
                    for (int j = childCount - 1; j >= 0; j--)
                    {
                        Transform child = areaEditorData.lockFloorNode.GetChild(j);
                        if (!child.name.Contains("sfx_"))
                        {
                            GameObject.DestroyImmediate(child.gameObject);
                        }
                    }
//                    GameObject.DestroyImmediate(areaEditorData.lockFloorNode.gameObject);
                }
                // 未解锁集装箱节点
                if (areaEditorData.containerEffect)
                {
                    GameObject.DestroyImmediate(areaEditorData.containerEffect.gameObject);
                }
            }
            
            // 添加运行时组件
            CityRootLoadComponent cityLoadComponent = exportGO.AddComponent<CityRootLoadComponent>();
            cityLoadComponent.rootFloorNode = cityFloorEditor.rootFloorNode;
            cityLoadComponent.cityFloorDataConfig = AssetDatabase.LoadAssetAtPath<CityFloorDataConfig>(_exportDataFilePath);
            // 移除编辑器组件
            DestroyImmediate(cityFloorEditor);

            PrefabUtility.SaveAsPrefabAsset(exportGO, _exportPrefabFilePath);
            AssetDatabase.Refresh(); 
            
            Debug.Log("Prefab导出完成");
        }

        /// <summary>
        /// 导出Floor数据
        /// </summary>
        /// <param name="path"></param>
        void ExportCityFloor()
        {
            CityFloorDataConfig config = ScriptableObject.CreateInstance<CityFloorDataConfig>();
            
            config.areas = new List<CityFloorAreaData>();
            for (int i = 0; i < _cityFloorEditor.areas.Count; ++i)
            {
                config.areas.Add(ExportCityFloorArea(_cityFloorEditor.areas[i]));
            }

            config.Serialize();
            
            AssetDatabase.CreateAsset(config, _exportDataFilePath);
            AssetDatabase.Refresh();

            Debug.Log("数据导出完成");
            // Selection.activeObject = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(path);
        }

        /// <summary>
        /// 导出Area数据
        /// </summary>
        /// <param name="areaNode"></param>
        /// <returns></returns>
        CityFloorAreaData ExportCityFloorArea(CityFloorEditor.CityFloorEditorArea areaEditorData)
        {
            // 区域根节点
            Transform areaNode = areaEditorData.areaNode;
            
            CityFloorAreaData areaData = new CityFloorAreaData();
            areaData.areaId = areaEditorData.areaId;
            areaData.name = areaNode.name;
            
            // Wall节点
            areaData.wallNode = ExportCityFloorNode(areaEditorData.wallNode);
            // Ground节点
            areaData.groundNode = ExportCityFloorNode(areaEditorData.groundNode, false);
            // 解锁Floor节点
            areaData.unlockFloorNode = ExportCityFloorNode(areaEditorData.unlockFloorNode);        
            // 解锁Floor特效节点
            areaData.unlockEffectNode = ExportCityFloorNode(areaEditorData.unlockEffectNode);        
            // 未解锁Floor节点分层列表
            areaData.lockFloorNode = ExportCityFloorNode(areaEditorData.lockFloorNode, true, true); 
            // 显示墙hierarchy路径列表
            areaData.showWallHierarchyPaths = ExportShowWallHierarchyPaths(areaEditorData.showWalls);
            // 装箱特效节点
            areaData.containerEffectNode = ExportCityFloorNode(areaEditorData.containerEffect);        
            
            return areaData;
        }

        List<string> ExportShowWallHierarchyPaths(List<GameObject> showWalls)
        {
            List<string> showWallHierarchyPaths = new List<string>();
            string rootFloorNodeHierarchyPath = _cityFloorEditor.rootFloorNode.GetHierarchyPath()+"/";
            
            for (int i = 0; i < showWalls.Count; ++i)
            {
                string hierarachy = showWalls[i].transform.GetHierarchyPath();
                showWallHierarchyPaths.Add(hierarachy.Replace(rootFloorNodeHierarchyPath, ""));
            }
            
            return showWallHierarchyPaths;
        }
        
        /// <summary>
        /// 导出Node数据
        /// </summary>
        /// <param name="node">导出节点</param>
        /// <param name="recurve">是否递归遍历</param>
        /// <param name="ignorePrefab">是否忽略prefab</param>
        /// <returns></returns>
        CityFloorNodeData ExportCityFloorNode(Transform node, bool recurve = true, bool ignorePrefab = false)
        {
            if (node == null)
            {
                return null;
            }
            
            CityFloorNodeData nodeData = new CityFloorNodeData();
            nodeData.name = node.name;
            nodeData.localPosition = node.localPosition;
            nodeData.localEulerAngles = node.localEulerAngles;
            nodeData.localScale = node.localScale;
            nodeData.active = node.gameObject.activeSelf;
            if (IsPrefabInstance(node.gameObject) && !ignorePrefab)
            {
                // prefab
                var prefab = PrefabUtility.GetCorrespondingObjectFromOriginalSource(node.gameObject);
                string assetPath = AssetDatabase.GetAssetPath(prefab);
                ExportDependence(assetPath);
                if (_dependenceFilesDict.ContainsKey(assetPath))
                {
                    nodeData.prefabPath = _dependenceFilesDict[assetPath];
                }
            }
            else if (recurve && node.childCount > 0)
            {
                // child
                nodeData.children = new List<CityFloorNodeData>();
                for (int i = 0; i < node.childCount; ++i)
                {
                    Transform child = node.GetChild(i);
                    if (!child.name.Contains("sfx_"))
                    {
                        nodeData.children.Add(ExportCityFloorNode(child));
                    }
                }
            }
            
            return nodeData;
        }

        void CopyDependence()
        {
            int cnt = _dependenceFilesDict.Count;
            int i = 0;
            foreach (var pair in _dependenceFilesDict)
            {
                ++i;
                // 显示进度
                EditorUtility.DisplayProgressBar($"导出进度({i}/{cnt})", $"copy {pair.Key} => {pair.Value}", i/(float)cnt);
                if (pair.Key != pair.Value)
                {
                    // Debug.Log($"copy {pair.Key} => {pair.Value}");
                    AssetDatabase.CopyAsset(pair.Key, pair.Value);
                }
            }
            // 隐藏进度
            EditorUtility.ClearProgressBar();
            
            Debug.Log("Dependence拷贝完成");
        }

        /// <summary>
        /// 导出依赖资源
        /// </summary>
        /// <param name="prefab"></param>
        void ExportDependence(string assetPath)
        {
            string ext = Path.GetExtension(assetPath);
            if (ext != ".prefab")
            {
                Debug.LogError($"发现非prefab类型的依赖资源: {assetPath}");
                return;
            }
            
            // 判断资源是否已经记录
            if (_dependenceFilesDict.ContainsKey(assetPath))
            {
                return;
            }
                
            // 判断资源是否在ResourceAssets目录，在的话就不必复制了
            if (assetPath.Contains("Assets/ResourceAssets/"))
            {
                _dependenceFilesDict.Add(assetPath, assetPath);
                return;
            }
            
            // 不在ResourceAssets目录的资源，复制到指定目录
            string destAssetPath = GenerateAssetPath($"{_exportDependencePath}/{Path.GetFileName(assetPath)}");
            // AssetDatabase.CopyAsset(assetPath, destAssetPath);
            // Debug.Log($"copy {assetPath} => {destAssetPath}");
            _dependenceFilesDict.Add(assetPath, destAssetPath);
        }

        /// <summary>
        /// 生成资源唯一名称
        /// </summary>
        /// <param name="assetPath"></param>
        /// <returns></returns>
        string GenerateAssetPath(string assetPath)
        {
            string undeterminedAssetPath = assetPath;
            
            // 判断文件名是否重复
            int index = 0;
            if (_dependenceFilesDict.ContainsValue(assetPath))
            {
                string fileNameWithoutExt = Path.GetFileNameWithoutExtension(assetPath);
                string newFileNameWithoutExt;
                do
                {
                    // 生成新文件名
                    newFileNameWithoutExt = $"{fileNameWithoutExt}_{index}";
                    undeterminedAssetPath = assetPath.Replace(fileNameWithoutExt, newFileNameWithoutExt);
                    index++;
                } while (_dependenceFilesDict.ContainsValue(undeterminedAssetPath));
            }

            if (index > 0)
            {
                Debug.LogWarning($"发现同名文件，启用自动重命名: {assetPath} => {undeterminedAssetPath}");
            }

            return undeterminedAssetPath;
        }

        /// <summary>
        /// 判断GameObject是否是Prefab
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        bool IsPrefabInstance(GameObject obj)
        {
            var type = PrefabUtility.GetPrefabAssetType(obj);
            var status = PrefabUtility.GetPrefabInstanceStatus(obj);
            var isRoot = PrefabUtility.IsAnyPrefabInstanceRoot(obj);
            // 是否为预制体实例判断
            if (type == PrefabAssetType.NotAPrefab || status == PrefabInstanceStatus.NotAPrefab || !isRoot)
            {
                return false;
            }

            return true;
        }
        
        /// <summary>
        /// 清空控制台
        /// </summary>
        void ClearConsole()
        {
            var log = typeof(EditorWindow).Assembly.GetType("UnityEditor.LogEntries");
            MethodInfo clearMethod = log.GetMethod("Clear");
            clearMethod.Invoke(null, null);
        }

    }
}